# ANSI terminal output control routines

#   Akalabeth Re-Bourne
#   Copyright (C) 2008 Norman B. Lancaster
#
#    This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#   along with this program.  If not, see http://www.gnu.org/licenses/

# Sets the cursor to position X by Y, 0-based
# $1 X location
# $2 Y location
function ATGoto
{
	echo -ne "\033[$(($2+1));$(($1+1))H"
	return 0
}

# Clears the screen and homes the cursor with an ANSI escapement sequence
function ATClear
{
	echo -ne "\033[2J"
	
	# The GNOME terminal does not properly home the cursor, so we do it explicitly
	ATGoto 0 0
	
	return 0
}

# Sets the foreground color
# $1 Color to set. Values 0-7 have the normal meaning. Values 8-15 are those
#    same colors with the intensity bit set.
function ATFG
{
	if (( $1 > 7 )); then echo -ne "\033[9$(( $1 - 8 ))m";
	else echo -ne "\033[3${1}m"; fi
	
	return 0
}

# Sets the background color
# $1 Color to set. Values 0-7 have the normal meaning. Values 8-15 are those
#    same colors with the intensity bit set.
function ATBG
{
	if (( $1 > 7 )); then echo -ne "\033[10$(( $1 - 8 ))m";
	else echo -ne "\033[4${1}m"; fi
	
	return 0
}

# Resets all console output colors to the default
function ATDefault
{
	echo -ne "\033[0m"

	return 0
}

# Returns a string in gReturnValue describing a single keystroke. This blocks
# until at least one key has been processed.
function ATGetCh
{
	local previousByte

	ATGetRawByte
	
	# Regular character, pass back to the application
	if [[ "$gReturnValue" != "" ]]; then return 0;
	# Escapement character, begin escapement processing
	else
		ATGetRawByte
		# This is actually two escape presses in a row
		if [[ "$gReturnValue" == "" ]]; then gReturnValue="ESC";
		else
			# Store this byte away in case something needs to use it
			previousByte="$gReturnValue"
			
			# ^[[ sequence
			if [[ "$gReturnValue" == "[" ]]; then
				ATGetRawByte
				case $gReturnValue in
					# Arrow keys
					A ) gReturnValue="UP" ;;
					B ) gReturnValue="DOWN" ;;
					C ) gReturnValue="RIGHT" ;;
					D ) gReturnValue="LEFT" ;;
					# If we didn't find what we were looking for, just fall
					# through.
				esac
			fi
			# Otherwise this escapement was unrecognized and we return the
			# current contents of gReturnValue
		# The ESC key was pressed by itself, or we have a VERY slow terminal :D
		fi
	fi
	
	return 0
}

# Worker function for ATGetCh, gets individual bytes from the input stream in a
# blocking way.
function ATGetRawByte
{
	# Input loop
	while :; do
		# If there is no data to be processed, this throws an error message.
		# We redirect this to /dev/null so it does not show up on the screen.
		# We use the -n 1 switch to return only one byte, and -s to prevent
		# echoing.
		read -n 1 -s gReturnValue 2>/dev/null
		
		# If we have something, return
		if [[ -n "$gReturnValue" ]]; then break; fi
	done

	return 0
}

